package com.woniu.gateway.filter;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.commons.response.ResponseResult;
import com.woniu.commons.util.JWTUtil;
import com.woniu.commons.util.TokenEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
@Component //将过滤器注册到Spring容器中，使其生效
public class AuthFilter implements GatewayFilter, Ordered {

    //执行过滤
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.debug("过滤器执行过滤");
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String url = request.getURI().getPath();
        log.debug("-----AuthFilter is processing URL: {}", url);
        System.out.println("-----AuthFilter is processing URL: " + url);

        //判断是否登入
        if (requireAuth(url)) {
            //没匹配上
            //获取token，判断token是否过期，是否合法
            List<String> list = request.getHeaders().get("authorization");
            if (list == null || list.size() == 0) {
                //没有token，返回结果，终止请求
                return goLogin(response);
            }
            //校验token是否合法
            String token = list.get(0);
            TokenEnum verify = JWTUtil.verify(token);
            if (verify != TokenEnum.TOKEN_SUCCESS){
                return goLogin(response);
            }
            //假设没有登入，返回结果，终止请求
            return goLogin(response);
        }
        //匹配上了，继续执行下一个过滤器
        return chain.filter(exchange);
    }

    /*
    * 去登录
    */
    private static Mono<Void> goLogin(ServerHttpResponse response) {
        ResponseResult<Object> result = new ResponseResult<>(HttpStatus.SC_FORBIDDEN, "请登录", null);
        //将数据转换成byte数组
        byte[] data = null;
        try {
            data = new ObjectMapper().writeValueAsString(result).getBytes(StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //创建数据库缓存对象，设置数据
        DataBuffer buffer = response.bufferFactory().wrap(data);
        //设置响应头
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        //返回响应
        return response.writeWith(Mono.just(buffer));
    }

    //设置过滤器的执行顺序
    @Override
    public int getOrder() {
        return 0; // 设置过滤器的执行顺序
    }

    //判断是否需要登入
    private boolean requireAuth(String url) {
        //不需要登入的列出来
        List<String> urlList = Arrays.asList(
                "/user/login", "/user/register", "/goods/find*", "/kill/find*"
        );
        //spring提供的路径匹配器，判断url是否在不需要登入的列出来
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        //判断url是否在urlList中，如果在返回true，如果不在返回false
        AtomicBoolean res = new AtomicBoolean(true);
        //遍历urlList，判断url是否在urlList中，如果在返回true，如果不在返回false
        urlList.forEach((path) -> {
            if (antPathMatcher.match(path, url)) {
                log.debug("-----AuthFilter 匹配上了 processing URL: {} in urlList", url, path);
                //如果url在urlList中，返回true
                res.set(true);
                return;
            }
        });
        //如果url不在urlList中，返回false
        return res.get();
    }
}